/**
 * @file Pinia持久化插件配置
 * @description 配置Pinia状态持久化，使用localStorage存储状态
 * @date 2024-06-10
 */

import { PiniaPluginContext, StateTree, SubscriptionCallbackMutation } from 'pinia'

/**
 * 配置持久化选项
 */
export interface PersistOptions {
  /**
   * 存储键名前缀
   */
  prefix?: string;
  /**
   * 要持久化的状态路径
   */
  paths?: string[];
  /**
   * 存储引擎，默认为localStorage
   */
  storage?: Storage;
}

/**
 * 状态版本信息
 */
export interface StateVersion {
  version: string;
  updatedAt: number;
}

/**
 * Pinia存储选项扩展
 */
declare module 'pinia' {
  interface DefineStoreOptionsBase<S extends StateTree, Store> {
    /**
     * 持久化配置
     */
    persist?: boolean | {
      /**
       * 要持久化的路径
       */
      paths?: string[];
    };
  }
}

/**
 * 创建Pinia持久化插件
 * @param options 持久化配置选项
 * @returns Pinia插件
 */
export function createPiniaPersist(defaultOptions: PersistOptions = {}) {
  const prefix = defaultOptions.prefix || 'gps-'
  const storage = defaultOptions.storage || localStorage

  // 创建并返回插件
  return ({ store, options }: PiniaPluginContext) => {
    // @ts-ignore - 类型扩展
    if (!options.persist) return
    
    // 获取持久化配置
    // @ts-ignore - 类型扩展
    const persistOptions = typeof options.persist === 'boolean' 
      ? {} 
      // @ts-ignore - 类型扩展
      : options.persist

    // 构建存储key
    const storeKey = `${prefix}${store.$id}`
    
    // 获取需要持久化的路径
    const paths = persistOptions.paths || defaultOptions.paths || Object.keys(store.$state)
    
    // 恢复数据
    try {
      const storedState = storage.getItem(storeKey)
      if (storedState) {
        const savedState = JSON.parse(storedState) as Record<string, unknown>
        
        // 恢复状态
        store.$patch((state: StateTree) => {
          for (const path of paths) {
            if (savedState[path] !== undefined) {
              // @ts-ignore - 动态访问和设置属性
              state[path] = savedState[path]
            }
          }
        })
      }
    } catch (error) {
      console.error('恢复持久化状态失败:', error)
      // 出错时清除可能损坏的数据
      storage.removeItem(storeKey)
    }
    
    // 监听状态变化，保存到存储
    store.$subscribe(
      (_: SubscriptionCallbackMutation<StateTree>, state: StateTree) => {
        try {
          const toPersist: Record<string, unknown> = {}
          
          // 只保存指定路径的状态
          for (const path of paths) {
            // @ts-ignore - 动态访问属性
            toPersist[path] = state[path]
          }
          
          // 添加版本信息，便于后续版本兼容处理
          const metaInfo: StateVersion = {
            version: '1.0',
            updatedAt: Date.now()
          }
          
          toPersist.__meta = metaInfo
          
          // 保存到存储
          storage.setItem(storeKey, JSON.stringify(toPersist))
        } catch (error) {
          console.error('保存状态到持久化存储失败:', error)
        }
      },
      { detached: true } // 组件卸载后依然保持订阅
    )
  }
} 